﻿using Shop.Model.DB;
using Shop.Model.SpecGroup;
using Shop.RemoteModel.GoodsSpec.Model;
using WeDonekRpc.Client;
using WeDonekRpc.Helper;
using WeDonekRpc.Helper.IdGenerator;
using WeDonekRpc.SqlSugar;

namespace Shop.Repository.lmpl
{
    internal class SpecGroupRepository : ShopBaseRepository<DBGoodsSpecGroup, long>, ISpecGroupRepository
    {
        public SpecGroupRepository (ISqlClientFactory factory) : base(factory)
        {
        }
        public void Delete (long id, long[] specId)
        {
            ISqlQueue<DBGoodsSpecGroup> queue = base.BeginQueue();
            queue.Delete(a => a.Id == id);
            queue.Delete<DBGoodsSpec>(a => specId.Contains(a.Id));
            _ = queue.Submit();
        }
        public SpecGroupDto[] Gets (long goodsId)
        {
            return base.Gets<SpecGroupDto>(a => a.GoodsId == goodsId, "Sort");
        }
        public GoodsSpecGroup[] Sync (long goodsId, SpecGroup[] groups)
        {
            bool isExists = base.IsExist(c => c.GoodsId == goodsId);
            if (groups.IsNull() && isExists == false)
            {
                return null;
            }
            ISqlQueue<DBGoodsSpecGroup> queue = base.BeginQueue();
            if (isExists && groups.IsNull())
            {
                this.Clear(goodsId);
                return null;
            }
            return this._Sync(goodsId, groups, isExists);
        }
        private GoodsSpecGroup[] _Sync (long goodsId, SpecGroup[] groups, bool isExists)
        {
            ISqlQueue<DBGoodsSpecGroup> queue = base.BeginQueue();
            if (isExists)
            {
                queue.Delete(a => a.GoodsId == goodsId);
                queue.Delete<DBGoodsSpec>(a => a.GoodsId == goodsId);
            }
            List<DBGoodsSpec> specs = [];
            DBGoodsSpecGroup[] adds = groups.ConvertAll((a, i) =>
            {
                DBGoodsSpecGroup group = new DBGoodsSpecGroup
                {
                    GoodsId = goodsId,
                    GroupName = a.GroupName,
                    Id = IdentityHelper.CreateId(),
                    Sort = i + 1,
                };
                a.Spec.ForEach((c, k) =>
                {
                    specs.Add(new DBGoodsSpec
                    {
                        GoodsId = goodsId,
                        GroupId = group.Id,
                        Id = IdentityHelper.CreateId(),
                        SpecIcon = c.SpecIcon,
                        SpecName = c.SpecName,
                        Sort = k + 1
                    });
                });
                return group;
            });
            queue.Insert(specs);
            queue.Insert(adds);
            _ = queue.Submit();
            return adds.ConvertAll(a => new GoodsSpecGroup
            {
                GroupName = a.GroupName,
                Id = a.Id,
                Spec = specs.Convert(c => c.GroupId == a.Id, c => new GoodsSpec
                {
                    Id = c.Id,
                    SpecIcon = c.SpecIcon,
                    SpecName = c.SpecName
                }),
            });
        }
        public void Clear (long goodsId)
        {
            ISqlQueue<DBGoodsSpecGroup> queue = base.BeginQueue();
            queue.Delete(a => a.GoodsId == goodsId);
            queue.Delete<DBGoodsSpec>(a => a.GoodsId == goodsId);
            _ = queue.Submit();
        }

        public long Add (SpecGroupAddDto datum)
        {
            DBGoodsSpecGroup add = datum.ConvertMap<SpecGroupAddDto, DBGoodsSpecGroup>();
            add.Id = IdentityHelper.CreateId();
            base.Insert(add);
            return add.Id;
        }
        public void SetSort (Dictionary<long, int> sorts)
        {
            if (!base.Update(sorts.ConvertAll(a => new DBGoodsSpecGroup
            {
                Id = a.Key,
                Sort = a.Value
            }), "Sort"))
            {
                throw new ErrorException("shop.spec.group.set.fail");
            }
        }
        public void SetName (long id, string name)
        {
            if (!base.Update(a => a.GroupName == name, a => a.Id == id))
            {
                throw new ErrorException("shop.spec.group.name.set.fail");
            }
        }
    }
}
